package muilty_thread.java_current_practice_and_kernel.cp5;


import java.util.HashMap;
import java.util.Map;
import java.util.Random;

interface Computable<A, V>{
    V compute(A arg) throws InterruptedException;
}



class ExpensiveFunction implements Computable<Integer,Integer>{

    @Override
    public Integer compute(Integer arg) throws InterruptedException {
        Thread.sleep(1000);
        return new Random().nextInt(10);
    }
}

public class Memoizer<A,V> implements Computable<A,V>{

    private final Map<A, V> cache = new HashMap<>();
    private final Computable<A, V> c;

    public Memoizer(Computable<A, V> c) {
        this.c = c;
    }

    public static void main(String[] args) throws InterruptedException {

        Memoizer<Integer, Integer> mem = new Memoizer<>(new ExpensiveFunction());
        for (int i = 0; i < 10; i++) {
            new Thread(() ->{
                int random = new Random().nextInt(5);
                Integer compute = null;
                try {

                    compute = mem.compute(random);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(random);
            }).start();
        }
    }

    @Override
    public synchronized V compute(A arg) throws InterruptedException {
        V result = cache.get(arg);
        if (result == null) {
            result = c.compute(arg);
            cache.put(arg, result);
        }
        return result;
    }
}
